﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Windows;
using System.Text;
using Theodorus.Properties;

namespace Theodorus
{
	class HtmlResultsRenderer : IResultsRenderer
	{
		private readonly string _pageTemplate;
		private readonly string _tableTemplate;
		private readonly string _errorTemplate;
		private readonly string _responseTemplate;
	    private readonly string _jquery;

		readonly List<string> _results = new List<string>();

		public HtmlResultsRenderer()
		{
			var resourceInfo = Application.GetResourceStream(new Uri("/Web/PageTemplate.html", UriKind.Relative));
			if (resourceInfo != null)
				using (var sr = new StreamReader(resourceInfo.Stream))
				{
					_pageTemplate = sr.ReadToEnd();
				}

			var streamResourceInfo = Application.GetResourceStream(new Uri("/Web/TableTemplate.html", UriKind.Relative));
			if (streamResourceInfo != null)
				using (var sr = new StreamReader(streamResourceInfo.Stream))
				{
					_tableTemplate = sr.ReadToEnd();
				}

			var resourceStream = Application.GetResourceStream(new Uri("/Web/ErrorTemplate.html", UriKind.Relative));
			if (resourceStream != null)
				using (var sr = new StreamReader(resourceStream.Stream))
				{
					_errorTemplate = sr.ReadToEnd();
				}

			var stream = Application.GetResourceStream(new Uri("/Web/ResponseTemplate.html", UriKind.Relative));
			if (stream != null)
				using (var sr = new StreamReader(stream.Stream))
				{
					_responseTemplate = sr.ReadToEnd();
				}
						
		}

		public void Reset()
		{
			_results.Clear();
		}

		public void AddError(string query, string errorMessage)
		{
			var data = _errorTemplate.Replace("{{query}}", HttpUtility.HtmlEncode(query));
			data = data.Replace("{{result}}",  HttpUtility.HtmlEncode(errorMessage));
			_results.Add(data);
		}

		public void AddResponse(string query, string result, TimeSpan timings)
		{
			var data = _responseTemplate.Replace("{{query}}", Settings.Default.ShowQueryWithResults ? HttpUtility.HtmlEncode(query) : "");
			data = data.Replace("{{elapsed}}", timings.TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
			data = data.Replace("{{result}}", HttpUtility.HtmlEncode(result));
			_results.Add(data);
		}

		public void AddTable(string query, DataTable table, TimeSpan timings)
		{
			var data = _tableTemplate.Replace("{{query}}", Settings.Default.ShowQueryWithResults ? HttpUtility.HtmlEncode(query) : "");
			data = data.Replace("{{elapsed}}", timings.TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
			
			var header = table.Columns.Cast<DataColumn>().Select(item => "<th>" + 
                HttpUtility.HtmlEncode(item.ColumnName) + "</th>").Aggregate((a, b) => a + b);
			
			data = data.Replace("{{coldefs}}", header);

			var builder2 = new StringBuilder();
			var rowCount = 0;
			foreach(DataRow row in table.Rows)
			{
				builder2.AppendLine("<tr>");
			    builder2.Append(row.ItemArray.Select(item => "<td>" + 
                    HttpUtility.HtmlEncode(item.ToString()).Replace(Environment.NewLine,"<br/>") + "</td>").Aggregate((a, b) => a + b));
				builder2.AppendLine("</tr>");
				rowCount++;
				if (rowCount == Settings.Default.ResultsLimit)
				{
					if (table.Rows.Count > rowCount)
					{
						builder2.AppendFormat(
							"<tr><td colspan=\"{0}\">There are more results, but are not shown based on your result limits setting.</td></tr>", table.Columns.Count)
							.AppendLine();

					}
					break;
				}
			}
			data = data.Replace("{{data}}", builder2.ToString());
			_results.Add(data);
		}

		public string GetResults()
		{
		    return _results.Count > 0 ?
                _pageTemplate.Replace("{{tables}}", 
                    _results.Aggregate((a, b) => a + b)).Replace("{{jquery}}", _jquery) 
              : 
                _pageTemplate.Replace("{{tables}}", "No results");
		}

	    public bool HasResults()
	    {
	        return _results.Count > 0;
	    }
	}
}
